package repositories

import (
	"fmt"

	"gitee.com/kessil/chicory/internal/models"
	"gitee.com/kessil/chicory/internal/utils"
	"xorm.io/xorm"
)

type UserRepository struct {
	*Repository[models.User]
	db *xorm.Engine
}

func NewUserRepository(db *xorm.Engine) *UserRepository {
	return &UserRepository{
		Repository: NewRepository[models.User](db),
		db:         db,
	}
}

func (r *UserRepository) GetUserWithRoles(id int64) (*models.User, error) {
	user, err := r.GetByID(id)
	if err != nil {
		return nil, err
	}

	// 获取用户角色
	var roles []models.Role
	err = r.db.Table("role").
		Join("INNER", "user_role", "role.id = user_role.roleId").
		Where("user_role.userId = ?", id).
		Find(&roles)
	if err != nil {
		return nil, err
	}

	user.Roles = roles
	return user, nil
}

func (r *UserRepository) GetUserByUsername(username string) (*models.User, error) {
	var user models.User
	has, err := r.db.Where("username = ?", username).Get(&user)
	if err != nil {
		return nil, err
	}
	if !has {
		return nil, nil
	}
	return &user, nil
}

func (r *UserRepository) AddUserRole(userId, roleId int64) error {
	userRole := &models.UserRole{
		UserId: userId,
		RoleId: roleId,
	}
	if has, err := r.db.Table("user_role").Where("userId = ? AND roleId = ?", userId, roleId).Exist(); has {
		return err
	}
	_, err := r.db.Insert(userRole)
	return err
}

func (r *UserRepository) RemoveUserRole(userId, roleId int64) error {
	_, err := r.db.Where("userId = ? AND roleId = ?", userId, roleId).Delete(&models.UserRole{})
	return err
}

func (r *UserRepository) GetUserWithDetail(id int64) (*models.UserDetailRes, error) {
	var user models.UserDetailRes
	has, err := r.db.Table("user").ID(id).Get(&user)
	if err != nil {
		return nil, err
	}

	if !has {
		return nil, fmt.Errorf("user not found")
	}

	// 获取用户Profile
	// var profile models.Profile
	// _, err = r.db.Table("profile").Where("userId", id).Get(&profile)
	// if err != nil {
	// 	return nil, err
	// }
	user.Profile = &models.Profile{
		Gender:   user.Gender,
		Email:    user.Email,
		Address:  user.Address,
		Avatar:   user.Avatar,
		Nickname: user.Nickname,
	}
	// 获取用户角色
	var roles []*models.Role
	err = r.db.Table("role").
		Join("INNER", "user_role", "role.id = user_role.roleId").
		Where("user_role.userId = ?", id).
		Find(&roles)
	if err != nil {
		return nil, err
	}

	user.Roles = roles
	user.CurrentRole = roles[0]
	return &user, nil
}

// GetUserPrimaryRoleID 获取用户的主要角色ID
func (r *UserRepository) GetUserPrimaryRoleID(userID int64) (int64, error) {
	var userRole models.UserRole
	has, err := r.db.Where("userId = ?", userID).Get(&userRole)
	if err != nil {
		return 0, err
	}
	if !has {
		return 0, fmt.Errorf("user has no role")
	}
	return userRole.RoleId, nil
}

// GetUserRoles 获取用户的所有角色
func (r *UserRepository) GetUserRoles(userID int64) ([]models.Role, error) {
	var roles []models.Role
	err := r.db.Table("role").
		Join("INNER", "user_role", "role.id = user_role.roleId").
		Where("user_role.userId = ?", userID).
		Find(&roles)
	if err != nil {
		return nil, err
	}
	return roles, nil
}

// ListUserWithRoles 分页获取所有用户
func (r *UserRepository) ListUserWithRoles(filters map[string]interface{}, pageNo, pageSize int) (*models.UserListRes, error) {
	var entities []models.User
	session := r.db.NewSession()
	// 应用筛选条件
	if len(filters) > 0 {
		for field, value := range filters {
			if err := r.addFilterCondition(session, field, value); err != nil {
				return nil, err
			}
		}
	}
	total, err := session.Count(new(models.User))
	if err != nil {
		utils.Error(err.Error())
		return nil, err
	}

	// 重新应用筛选条件，因为session被Count重置了
	if len(filters) > 0 {
		for field, value := range filters {
			if err := r.addFilterCondition(session, field, value); err != nil {
				return nil, err
			}
		}
	}
	if pageNo > 0 && pageSize > 0 {
		session = session.Limit(pageSize, (pageNo-1)*pageSize)
	}

	err = session.Table("user").Find(&entities)
	if err != nil {
		utils.Error(err.Error())
		return nil, err
	}

	for key, user := range entities {
		roles, _ := r.GetUserRoles(user.Id)
		entities[key].Roles = roles
	}

	return &models.UserListRes{PageData: entities, Total: total}, nil

}

// 重置用户密码
func (r *UserRepository) ResetPassword(userId int64, pass string) error {
	user, err := r.GetByID(userId)
	if err != nil {
		return err
	}
	// if !user.CheckPassword(pass.OldPassword) {
	// 	return errors.New("old password wrong")
	// }
	return user.SetPassword(pass)

}
